/*
 * 文件名：ReflectionUtils
 * 版权：Copyright @ 2017 excel All Rights Reserved.
 * 描述：
 * 修改人：lemon
 * 修改时间：2017年9月24日 下午12:47:32
 * 修改内容：〈修改内容〉
 */
package com.ctcemti.mdm.common.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @desc: excel
 * @author: lemon
 * @createTime: 2017年9月24日 下午12:47:32
 * @history:
 * @version: v1.0
 */
public class ReflectionUtils {
	/**
	 * 通过反射, 获得定义 Class 时声明的父类的泛型参数的类型 
	 * 如: public EmployeeDao extends BaseDao<Employee, String>
	 * @param clazz
	 * @param index
	 * @return
	 */
	public static Class<?> getSuperClassGenricType(Class<?> clazz, int index) {
		Type genType = clazz.getGenericSuperclass();

		if (!(genType instanceof ParameterizedType)) {
			return Object.class;
		}

		Type[] params = ((ParameterizedType) genType).getActualTypeArguments();

		if (index >= params.length || index < 0) {
			return Object.class;
		}

		if (!(params[index] instanceof Class)) {
			return Object.class;
		}

		return (Class<?>) params[index];
	}

	/**
	 * 通过反射, 获得 Class 定义中声明的父类的泛型参数类型 如: public EmployeeDao extends
	 * BaseDao<Employee, String>
	 * 
	 * @param <T>
	 * @param clazz
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> Class<T> getSuperGenericType(Class<?> clazz) {
		return (Class<T>) getSuperClassGenricType(clazz, 0);
	}

	/**
	 * 循环向上转型, 获取对象的 DeclaredMethod
	 * @param object
	 * @param methodName
	 * @param parameterTypes
	 * @return
	 */
	@SuppressWarnings("unused")
	public static Method getDeclaredMethod(Object object, String methodName,
			Class<?>[] parameterTypes) throws Exception {

		for (Class<?> superClass = object.getClass(); superClass != Object.class; 
				superClass = superClass.getSuperclass()) {
			// superClass.getMethod(methodName, parameterTypes);
			return superClass.getDeclaredMethod(methodName, parameterTypes);
			// Method 不在当前类定义, 继续向上转型
			// ..
		}
		return null;
	}

	/**
	 * 循环向上转型, 获取对象的 DeclaredField
	 * @param clazz
	 * @param filedName
	 * @return
	 */
	@SuppressWarnings("unused")
	public static Field getDeclaredField(Class clazz, String filedName) throws Exception {
		Field[] fields = clazz.getDeclaredFields();
		for (Field field : fields) {
			if (field.getName().equals(filedName)) {
				return clazz.getDeclaredField(filedName);
			}
		}
		if (clazz.getSuperclass() != Object.class) {
			return getDeclaredField(clazz.getSuperclass(), filedName);
		}
		return null;
//		for (Class<?> superClass = object.getClass(); superClass != Object.class;
//				superClass = superClass.getSuperclass()) {
//			// Field 不在当前类定义, 继续向上转型
//			return superClass.getDeclaredField(filedName);
//		}
	}

	/**
	* 执行方法 
	* 直接调用对象方法, 而忽略修饰符(private, protected)
	* @author: lemon
	* @createTime: 2017年9月24日 下午7:17:44
	* @history:
	* @param object
	* @param methodName
	* @param parameterTypes
	* @param parameters
	* @return
	* @throws Exception Object
	 */
	public static Object invokeMethod(Object object, String methodName,
			Class<?>[] parameterTypes, Object[] parameters) throws Exception {

		Method method = getDeclaredMethod(object, methodName, parameterTypes);

		if (method == null) {
			throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + object + "]");
		}

		method.setAccessible(true);

		return method.invoke(object, parameters);
	}

	/**
	* 设置字段值 
	* 直接设置对象属性值, 忽略 private/protected 修饰符, 也不经过 setter
	* @author: lemon
	* @createTime: 2017年9月24日 下午7:08:37
	* @history:
	* @param object
	* @param fieldName
	* @param value
	* @throws Exception void
	 */
	@SuppressWarnings("deprecation")
	public static void setFieldValue(Object object, String fieldName, Object value) throws Exception {
		if (value == null) {
			return;
		}
		
		Field field = getDeclaredField(object.getClass(), fieldName);

		if (field == null) {
			throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]");
		}
		
		makeAccessible(field);
		
		Class<?> fieldType = field.getType();
		Object valObj = null;
		if (fieldType == String.class) {
			valObj = value.toString();
		} else if (fieldType == int.class || fieldType == Integer.class) {
			String str = value.toString();
			if (str.contains(".")) {
				str = str.substring(0, str.lastIndexOf("."));
			}
			valObj = Integer.valueOf(str);
		} else if (fieldType == float.class || fieldType == Float.class) {
			valObj = Float.valueOf(value.toString());
		} else if (fieldType == Short.class) {
			String str = value.toString();
			if (str.contains(".")) {
				str = str.substring(0, str.lastIndexOf("."));
			}
			valObj = Short.valueOf(str);
		} else if (fieldType == double.class || fieldType == Double.class) {
			valObj = Double.valueOf(value.toString());
		} else if (fieldType == Date.class) {
			valObj = new Date(value.toString());
		} else if (fieldType == BigDecimal.class) {
			valObj = new BigDecimal(value.toString());
		}
		field.set(object, valObj);
	}

	/**
	* 获取字段值
	* 直接读取对象的属性值, 忽略 private/protected 修饰符, 也不经过 getter
	* @author: lemon
	* @createTime: 2017年9月24日 下午7:04:54
	* @history:
	* @param object
	* @param fieldName
	* @return Object
	* @throws Exception 
	 */
	public static Object getFieldValue(Object object, String fieldName) throws Exception {
		Field field = getDeclaredField(object.getClass(), fieldName);

		if (field == null) {
			throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]");
		}

		makeAccessible(field);
		Object value = field.get(object);
		Class<?> fieldType = field.getType();
		Object valObj = null;
		if (fieldType == String.class) {
			valObj = value.toString();
		} else if (fieldType == int.class || fieldType == Integer.class) {
			valObj = Integer.valueOf(value.toString());
		} else if (fieldType == float.class || fieldType == Float.class) {
			valObj = Float.valueOf(value.toString());
		} else if (fieldType == double.class || fieldType == Double.class) {
			valObj = Double.valueOf(value.toString());
		} else if (fieldType == Date.class) {
			valObj = (Date)value;
			SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
			valObj = format.format(valObj);
		}
		return valObj;
	}
	
	/**
	* 使 filed 变为可访问
	* @author: lemon
	* @createTime: 2017年9月24日 下午7:20:11
	* @history:
	* @param field void	字段
	 */
	private static void makeAccessible(Field field) {
		if (!Modifier.isPublic(field.getModifiers())) {
			field.setAccessible(true);
		}
	}
	/**
	 * 判断对象是否有属性为空
	*
	* @author: rucheng
	* @createTime: 2018年7月30日 上午10:12:48
	* @history:
	* @param obj
	* @return
	* @throws Exception boolean
	 */
	public static boolean isHasFieldNull(Object obj) throws Exception{
        Class stuCla = (Class) obj.getClass();// 得到类对象
        Field[] fs = stuCla.getDeclaredFields();//得到属性集合
        boolean flag = false;
        for (Field f : fs) {//遍历属性
            f.setAccessible(true); // 设置属性是可以访问的(私有的也可以)
            Object val = f.get(obj);// 得到此属性的值
            if(null==f) {//只要有1个属性不为空,那么就不是所有的属性值都不为空
                flag = true;
                break;
            }
        }
        return flag;
    }
}
